package org.ceteca.explica.core.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.Date;

import org.ceteca.explica.core.util.Converter;
import org.ceteca.explica.core.util.DateTime;
import org.ceteca.explica.core.util.InterfaceValidator;

public final class FieldValue {
	public static Object getFieldValue(Class c, String fieldName, String val) {
		Object value = null;
		
		try {
			if (c != null && fieldName != null && val != null) {
				Field[]	l = c.getDeclaredFields();
				for (int i=0; l != null && i<l.length; i++) {
					System.out.println("Declared Field: " + i + " = " + l[i].getName() + " (" + l[i].getType() + ")");
				}
				
				if (l == null || l.length <= 0)
					System.out.println("NO DECLARED FIELDS");
				
				Field f = c.getDeclaredField(fieldName);
				if (f != null) {
					Class fieldType = f.getType();
					if (fieldType.isPrimitive()) {
						if (fieldType.getName().equalsIgnoreCase("int")) {
							value = new Integer(val);
						}
						else if (fieldType.getName().equalsIgnoreCase("short")) {
							value = new Short(val);
						}
						else if (fieldType.getName().equalsIgnoreCase("long")) {
							value = new Long(val);
						}
						else if (fieldType.getName().equalsIgnoreCase("float")) {
							value = new Float(val);
						}
						else if (fieldType.getName().equalsIgnoreCase("double")) {
							value = new Double(val);
						}
						else if (fieldType.getName().equalsIgnoreCase("boolean")) {
							value = Boolean.parseBoolean(val);
						}
						else if (fieldType.getName().equalsIgnoreCase("byte")) {
							value = new Byte(val.getBytes()[0]);
						}
						else if (fieldType.getName().equalsIgnoreCase("char")) {
							value = new Character(val.toCharArray()[0]);
						}
						else {
							value = null;
						}
					}
					else if (fieldType.newInstance() instanceof Integer) {
						value = new Integer(val);
					}
					else if (fieldType.equals(BigDecimal.class)) {
						value = new BigDecimal(val);
					} 
					else if (fieldType.newInstance() instanceof Date) {
						DateTime dt = new DateTime(val, InterfaceValidator.CONST_DATE_PATTERN);
						value = dt.getDate();
					}
					else if (fieldType.newInstance() instanceof Boolean) {
						value = Boolean.parseBoolean(val);
					}
					else if (fieldType.newInstance() instanceof String) {
						value = val;
					}
					else if (fieldType.newInstance() instanceof Long) {
						value = new Long(val);
					}
					else if (fieldType.isArray() && fieldType.getComponentType().newInstance() instanceof Byte) {
						value = val.toCharArray();
					}
					else {
						value = null;
					}
				}
			}
		}
		catch (Exception ex) {
			ex.printStackTrace();
			value = null;
		}
		
		return value;
	}
	
	public static String parseFieldValue(Object o, String fieldId) {
		String value = null;
		if (o == null || fieldId.isEmpty())
			return "NULL";

		// Format the field id with the Java default format for getters with the first letter of the field capitalized
		String id = fieldId.substring(0, 1).toUpperCase();
		id += fieldId.substring(1, fieldId.length());
		// Get the getter method for the correspondent field
		try {
			Object[] args = {};
			Method m = o.getClass().getMethod("get" + id, (Class[])null);
			if (m != null) {
				Object v = m.invoke(o, args);
				if (v == null) {
					value = "NULL";
				}
				else {
					value = FieldValue.parseFieldValue(m.getReturnType(), v);
				}
			} // if a getter has been found
		} // try
		catch (Exception ex) {
			ex.printStackTrace();
			value = "NULL";
		} // catch
		
		return value;
	}
	
	private static String parseFieldValue(Class type, Object val) {
		String value = null;
		
		try {
			if (val != null && type != null) {
				if (type.isPrimitive()) {
					if (type.getName().equalsIgnoreCase("int")) {
						value = Converter.getInstance().toString((Integer)val);
					}
					else if (type.getName().equalsIgnoreCase("short")) {
						value = Converter.getInstance().toString((Short)val);
					}
					else if (type.getName().equalsIgnoreCase("long")) {
						value = Converter.getInstance().toString((Long)val);
					}
					else if (type.getName().equalsIgnoreCase("float")) {
						value = Converter.getInstance().toString((Float)val);
					}
					else if (type.getName().equalsIgnoreCase("double")) {
						value = Converter.getInstance().toString((Double)val);
					}
					else if (type.getName().equalsIgnoreCase("boolean")) {
						value = ((Boolean)val).toString();
					}
					else if (type.getName().equalsIgnoreCase("byte")) {
						value = Converter.getInstance().toString((Byte)val);
					}
					else if (type.getName().equalsIgnoreCase("char")) {
						value = "" + (Character)val;
					}
					else {
						value = null;
					}
				}
				else {
					if (type.equals(BigDecimal.class)) {
						value = Converter.getInstance().toString((BigDecimal)val);
					} // if type == BigDecimal
					else {
						Object ins = type.newInstance();
						if (ins instanceof Integer) {
							value = Converter.getInstance().toString((Integer)val);
						}
						else if (ins instanceof Date) {
							value = Converter.getInstance().toString((Date)val);
						}
						else if (ins instanceof java.util.Date) {
							value = Converter.getInstance().toString((Date)val);
						}
						else if (ins instanceof Boolean) {
							value = ((Boolean)val).toString();
						}
						else if (ins instanceof String) {
							value = (String)val;
						}
						else if (ins instanceof Long) {
							value = Converter.getInstance().toString((Long)val);
						}
						else if (type.isArray() && type.getComponentType().newInstance() instanceof Byte) {
							value = ((Byte)val).toString();
						}
						else {
							value = null;
						}
					} // else no big decimal
				}
			}
		}
		catch (Exception ex) {
			ex.printStackTrace();
			value = null;
		}
		
		return value;
	}
}
